package org.sardine.aop;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.regex.Pattern;

import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.log4j.Logger;
import org.sardine.util.ClassUtils;
import org.sardine.util.Wildcard;

public class JavaDynamicAopProxy implements AopProxy,InvocationHandler{
	
	private final Logger log = Logger.getLogger(JavaDynamicAopProxy.class);
	private ProxySupport support;
	
	public JavaDynamicAopProxy(ProxySupport support){
		this.support = support;
	}

	public Object getProxy() {
		return getProxy(ClassUtils.getDefaultClassLoader());
	}

	public Object getProxy(ClassLoader classLoader) {
		return Proxy.newProxyInstance(classLoader, support.getProxiedTargetInterfaces(), this);
	}

	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		
		Object returnVal = null;
		MethodInvocation invocation = null;
		Object target = support.getTarget();
		List<Advice> interceptors = support.getInterceptors();
		
		/*
		if(interceptors.isEmpty() || !isTargetMethod(method)){
			returnVal = AopUtils.invoke(target, method, args);
		}else{
			invocation = new ReflectiveMethodInvocation(proxy,target,method,args,interceptors);
			returnVal = invocation.proceed();
		}*/
		if(interceptors.isEmpty()){
			returnVal = AopUtils.invoke(target, method, args);
			
		}else{
			log.debug("MethodNamePatterns size is "+support.getMethodNamePatterns().size());
			if(support.getMethodNamePatterns().size()>0){
				
				if(!matchMethodNamePattern(method)){
					return AopUtils.invoke(target, method, args);
				}
			}
			invocation = new ReflectiveMethodInvocation(proxy,target,method,args,interceptors);
			returnVal = invocation.proceed();
		}
		
		return returnVal;
	}

	public Object getProxy(Object[] targetConstructorParameters) {
		return getProxy();
	}
	
	private boolean matchMethodNamePattern(Method method){
		
		String className = method.getDeclaringClass().getName();
		String methodName = method.getName();
		
		return support.matchMethodNamePattern(className, methodName);
		
	}

}
